package top.xiangqifu.springboot2_auth.interceptor;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import top.xiangqifu.springboot2_auth.entity.AuthInfo;
import top.xiangqifu.springboot2_auth.utils.AuthInfoUtils;
import top.xiangqifu.springboot2_auth.utils.IpUtils;
import top.xiangqifu.springboot2_auth.utils.JwtUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
@RequiredArgsConstructor
public class AppInterceptor implements HandlerInterceptor {

    public static final String TOKEN_HEADER = "Authorization";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("拦截器前置功能{}", request.getRequestURI());
        boolean controller = (handler instanceof HandlerMethod);
        if (!controller) {
            return true;
        }
        HandlerMethod hm = (HandlerMethod) handler;
        log.debug("控制类:{},{}", hm.getBeanType().getName(), hm.getMethod().getName());
        //获取控制器类的路径信息
        Class<?> clazz = hm.getBeanType();
        RequestMapping clazzMapping = clazz.getAnnotation(RequestMapping.class);
        if (clazzMapping == null || clazzMapping.value() == null || clazzMapping.value().length == 0) {
            return true;
        }
        String cpath = clazzMapping == null ? "" : clazzMapping.value()[0];
        //获取控制器类的方法路径信息
        RequestMapping methodMapping = hm.getMethodAnnotation(RequestMapping.class);
        if (methodMapping == null || methodMapping.value() == null || methodMapping.value().length == 0) {
            return true;
        }
        String mpath = methodMapping == null ? "" : methodMapping.value()[0];
        log.debug("拦截器拦截路径信息L{}", cpath + mpath);
        //请求的原始路径
        String requestPath = request.getRequestURI();
        //请求的method
        String method = request.getMethod();
        //将相关信息放置到线程现场中（方便后续的业务逻辑中使用）
        AuthInfo authInfo=new AuthInfo();
        authInfo.setIp(IpUtils.getIpAddress());
        authInfo.setMethod(method);
        authInfo.setMappingPath(String.format("%s%s", cpath, mpath));
        authInfo.setRequestUrl(requestPath);
        //token处理
        String token = request.getHeader(TOKEN_HEADER);
        authInfo.setToken(token);
        authInfo.setUserId(JwtUtils.parseUserIdToken(token));
        log.debug("授权信息：{}", authInfo);
        AuthInfoUtils.put(authInfo);
        log.debug("拦截器拦截路径信息R{},{}", requestPath, method);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.debug("拦截器尾置功能");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.debug("拦截器功能完成");
    }
}
